/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkGb28181Ut.h"
#include "MkEvent/MkEvent.h"
#include "MkEvent/MkEventPool.h"
#include "MkEvent/MkTimer.h"
#include "MkUtil/MkUtil.h"
#include "MkMedia/MkFileSource.h"
#include "MkMedia/MkMediaConsumer.h"
#include "MkUtil/MkLog.h"
#include "MkRtp/MkRtpServerPool.h"
#include "MkGbMedia/MkGbMediaServer.h"
#include "MkGbMedia/MkGbMediaEndUser.h"
#include "MkGb28181/MkGbUtil.h"
#include "MkGb28181/MkGbPtz.h"
#include "MkUtil/MkBase64.h"
#include "MkUtil/MkMd5.h"
#include "MkSdp/MkSdp.h"
#include <gtest/gtest.h>
#ifndef _WIN32
#include "MkUtil/MkMemQueue.h"
#endif

CMkGb28181Test::CMkGb28181Test(CMkEventPool* pEventPool, CMkTimer* pTimer)
    : CMkGb28181(pEventPool, pTimer)
{
    CMkUtil::Utf8ToGbk("测试设备", m_DeviceName);

    m_ChannelItem.Address = "Address";
    m_ChannelItem.CivilCode = "3402000000";
    m_ChannelItem.DeviceID = "34020000001310000001";
    m_ChannelItem.Manufacturer = "Mk";
    m_ChannelItem.Model = "Ipc Camera";
    CMkUtil::Utf8ToGbk("测试通道", m_ChannelItem.Name);
    m_ChannelItem.Owner = "Owner";
    m_ChannelItem.ParentID = "34020000002000000001";
    m_ChannelItem.Parental = "0";
    m_ChannelItem.RegisterWay = "1";
    m_ChannelItem.SafetyWay = "0";
    m_ChannelItem.Secrecy = "0";
    m_ChannelItem.Status = "ON";

    m_AlarmItem.Address = "Address";
    m_AlarmItem.CivilCode = "3402000000";
    m_AlarmItem.DeviceID = "34020000001340000001";
    m_AlarmItem.Manufacturer = "Mk";
    m_AlarmItem.Model = "Alarm Out";
    CMkUtil::Utf8ToGbk("测试报警", m_AlarmItem.Name);
    m_AlarmItem.Owner = "Owner";
    m_AlarmItem.ParentID = "34020000002000000001";
    m_AlarmItem.Parental = "0";
    m_AlarmItem.RegisterWay = "1";
    m_AlarmItem.SafetyWay = "0";
    m_AlarmItem.Secrecy = "0";
    m_AlarmItem.Status = "ON";

    m_AudioOutItem.Address = "Address";
    m_AudioOutItem.CivilCode = "3402000000";
    m_AudioOutItem.DeviceID = "34020000001370000001";
    m_AudioOutItem.Manufacturer = "Mk";
    m_AudioOutItem.Model = "Audio Out";
    CMkUtil::Utf8ToGbk("测试语音通道", m_AudioOutItem.Name);
    m_AudioOutItem.Owner = "Owner";
    m_AudioOutItem.ParentID = "34020000002000000001";
    m_AudioOutItem.Parental = "0";
    m_AudioOutItem.RegisterWay = "1";
    m_AudioOutItem.SafetyWay = "0";
    m_AudioOutItem.Secrecy = "0";
    m_AudioOutItem.Status = "ON";

    m_SnapShot.MainParam["SnapNum"] = "1";
    m_SnapShot.MainParam["Interval"] = "2";
    m_SnapShot.MainParam["UploadUrl"] = "http://12.12.12.12/api/pic";
    m_SnapShot.MainParam["SessionID"] = "123";

    m_FrameMirrorType = 1;

    MkGbMessage SVCParamMsg;
    SVCParamMsg.MainParam["SVCSTMMode"] = "1";
    SVCParamMsg.MainParam["SVCSpaceSupportMode"] = "1";
    SVCParamMsg.MainParam["SVCTimeSupportMode"] = "1";
    MkGbMessage SurveillanceParamMsg;
    SurveillanceParamMsg.MainParam["TimeShowFlag"] = "1";
    SurveillanceParamMsg.MainParam["OSDShowFlag"] = "1";
    SurveillanceParamMsg.MainParam["AIShowFlag"] = "1";
    SurveillanceParamMsg.MainParam["GISShowFlag"] = "1";
    m_SVACDecodeConfig.MapMessage["SVCParam"] = SVCParamMsg;
    m_SVACDecodeConfig.MapMessage["SurveillanceParam"] = SurveillanceParamMsg;

    MkGbMessage ROIParamMsg;
    ROIParamMsg.MainParam["ROIFlag"] = "1";
    ROIParamMsg.MainParam["ROINumber"] = "1";
    ROIParamMsg.ItemName = "Item";
    MkGbMessage GbChild;
    GbChild.MainParam["ROISeq"] = "1";
    GbChild.MainParam["TopLeft"] = "1";
    GbChild.MainParam["BottomRight"] = "1";
    GbChild.MainParam["ROIQP"] = "1";
    ROIParamMsg.VecChildren.emplace_back(GbChild);
    m_SVACEncodeConfig.MapMessage["ROIParam"] = ROIParamMsg;

    MkGbMessage SVCParamMsg1;
    SVCParamMsg1.MainParam["SvCSpaceDomainMode"] = "1";
    SVCParamMsg1.MainParam["SVCTimeDomainMode"] = "1";
    SVCParamMsg1.MainParam["SSVCRatioValue"] = "1";
    SVCParamMsg1.MainParam["SVCSpaceSupportMode"] = "1";
    SVCParamMsg1.MainParam["SVCTimeSupportMode"] = "1";
    SVCParamMsg1.MainParam["SSVCRatioSupportList"] = "4:3/2:1";
    m_SVACEncodeConfig.MapMessage["SVCParam"] = SVCParamMsg1;

    MkGbMessage SurveillanceParamMsg1;
    SurveillanceParamMsg1.MainParam["TimeFlag"] = "1";
    SurveillanceParamMsg1.MainParam["OSDFlag"] = "1";
    SurveillanceParamMsg1.MainParam["AIFlag"] = "1";
    SurveillanceParamMsg1.MainParam["GISFlag"] = "1";
    m_SVACEncodeConfig.MapMessage["SVCParam"] = SurveillanceParamMsg1;

    MkGbMessage AudioParamMsg;
    AudioParamMsg.MainParam["AudioRecognitionFlag"] = "1";
    m_SVACEncodeConfig.MapMessage["AudioParam"] = AudioParamMsg;



    GbChild.MainParam.clear();
    GbChild.MainParam["StreamNumber"] = "0";
    GbChild.MainParam["VideoFormat"] = "2";
    GbChild.MainParam["Resolution"] = "2";
    GbChild.MainParam["FrameRate"] = "25";
    GbChild.MainParam["BitRateType"] = "1";
    GbChild.MainParam["VideoBitRate"] = "1";
    m_VideoParamAttribute.VecChildren.emplace_back(GbChild);
    GbChild.MainParam["StreamNumber"] = "1";
    m_VideoParamAttribute.VecChildren.emplace_back(GbChild);
    GbChild.MainParam["StreamNumber"] = "2";
    m_VideoParamAttribute.VecChildren.emplace_back(GbChild);
    m_VideoParamAttribute.ChildKey = "VideoParamAttribute";
    m_VideoParamAttribute.ItemName = "Item";

    m_VideoRecordPlan.MainParam["RecordEnable"] = "1";
    m_VideoRecordPlan.MainParam["RecordScheduleSumNum"] = "7";
    m_VideoRecordPlan.MainParam["StreamNumber"] = "1";
    MkGbMessage RecordScheduleMsg;
    RecordScheduleMsg.MainParam["WeekDayNum"] = "1";
    RecordScheduleMsg.MainParam["TimeSegmentSumNum"] = "2";
    RecordScheduleMsg.ChildKey = "TimeSegment";
    MkGbMessage TimeSegmentMsg;
    TimeSegmentMsg.MainParam["StartHour"] = "0";
    TimeSegmentMsg.MainParam["StartMin"] = "0";
    TimeSegmentMsg.MainParam["StartSec"] = "0";
    TimeSegmentMsg.MainParam["StopHour"] = "1";
    TimeSegmentMsg.MainParam["StopMin"] = "0";
    TimeSegmentMsg.MainParam["StopSec"] = "0";
    RecordScheduleMsg.VecChildren.emplace_back(TimeSegmentMsg);
    TimeSegmentMsg.MainParam["StartHour"] = "1";
    TimeSegmentMsg.MainParam["StartMin"] = "0";
    TimeSegmentMsg.MainParam["StartSec"] = "0";
    TimeSegmentMsg.MainParam["StopHour"] = "2";
    TimeSegmentMsg.MainParam["StopMin"] = "0";
    TimeSegmentMsg.MainParam["StopSec"] = "0";
    RecordScheduleMsg.VecChildren.emplace_back(TimeSegmentMsg);
    m_VideoRecordPlan.MapMessage["RecordSchedule"] = RecordScheduleMsg;

    m_VideoParamOpt.MainParam["DownloadSpeed"] = "0.25/1/2/4";
    m_VideoParamOpt.MainParam["Resolution"] = "1/2/3/4/5";

    m_AlarmReport.MainParam["MotionDetection"] = "1";
    m_AlarmReport.MainParam["FieldDetection"] = "1";

    m_PictureMask.MainParam["On"] = "1";
    m_PictureMask.MainParam["SumNum"] = "3";
    m_PictureMask.ChildKey = "RegionList";
    GbChild.MainParam.clear();
    GbChild.MainParam["Seq"] = "1";
    GbChild.MainParam["Point"] = "20,30,30,30";
    m_PictureMask.VecChildren.emplace_back(GbChild);
    GbChild.MainParam["Seq"] = "2";
    m_PictureMask.VecChildren.emplace_back(GbChild);
    GbChild.MainParam["Seq"] = "3";
    m_PictureMask.VecChildren.emplace_back(GbChild);

    m_VideoAlarmRecord.MainParam["RecordEnable"] = "1";
    m_VideoAlarmRecord.MainParam["RecordTime"] = "1";
    m_VideoAlarmRecord.MainParam["PreRecordTime"] = "5";
    m_VideoAlarmRecord.MainParam["StreamNumber"] = "1";

    m_OSDConfig.MainParam["Length"] = "1";
    m_OSDConfig.MainParam["Width"] = "1";
    m_OSDConfig.MainParam["TimeX"] = "1";
    m_OSDConfig.MainParam["TimeY"] = "1";
    m_OSDConfig.MainParam["TimeEnable"] = "1";
    m_OSDConfig.MainParam["TimeType"] = "1";
    m_OSDConfig.MainParam["TextEnable"] = "1";
    m_OSDConfig.MainParam["SumNum"] = "2";
    m_OSDConfig.ChildKey = "Item";
    GbChild.MainParam.clear();
    MkString StrGbk;
    CMkUtil::Utf8ToGbk("你好", StrGbk);
    GbChild.MainParam["Text"] = StrGbk;
    GbChild.MainParam["X"] = "0";
    GbChild.MainParam["Y"] = "1";
    m_OSDConfig.VecChildren.emplace_back(GbChild);
    CMkUtil::Utf8ToGbk("你好--你好", StrGbk);
    GbChild.MainParam["Text"] = StrGbk;
    GbChild.MainParam["X"] = "110";
    GbChild.MainParam["Y"] = "211";
    m_OSDConfig.VecChildren.emplace_back(GbChild);

    m_MapPreset["1"] = "1";
    m_MapPreset["2"] = "2";

    MkGbCruisePoint Point1;
    Point1.CruisePreindex = "1";
    Point1.CruiseSpeed = "15";
    Point1.CruiseStayTime = "5";

    MkCruiseTrack Track;
    Track.MapCruiseTrack[Point1.CruisePreindex] = Point1;
    Point1.CruisePreindex = "2";
    Track.MapCruiseTrack[Point1.CruisePreindex] = Point1;
    Track.CruiseId = "1";
    Track.CruiseName = "1";
    m_MapCruiseTrack[Track.CruiseId] = Track;
    Track.CruiseId = "2";
    Track.CruiseName = "2";
    m_MapCruiseTrack[Track.CruiseId] = Track;

    m_HomePositonParam["Enable"] = "1";
    m_HomePositonParam["PresetIndex"] = "1";
    m_HomePositonParam["ResetTime"] = "1";
}

CMkGb28181Test::~CMkGb28181Test()
{

}

Uint32 CMkGb28181Test::Start(const MkGbStartParam& Param)
{
    return CMkGb28181::Start(Param, [this](const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb) {
        return OnGbRequest(pGbReq, Cb);
    });
}

Uint32 CMkGb28181Test::OnGbRequest(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    Uint32 ErrorCode = NoneError;
    switch (pGbReq->m_RequestType) {
    case MkGbRequestDeviceAuthor:
        ErrorCode = OnGbDeviceAuthor(pGbReq, Cb);
        break;
    case MkGbRequestMessage:
        ErrorCode = OnGbMessageRequest(dynamic_cast<const CMkGbMessageRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestNotify:
        ErrorCode = OnGbNotifyReqeust(dynamic_cast<const CMkGbNotifyRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestSubscribe:
        ErrorCode = OnGbSubscribeRequest(dynamic_cast<const CMkGbSubscribeRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestInvite:
        ErrorCode = OnGbInviteRequest(dynamic_cast<const CMkGbInviteReqeust*>(pGbReq), Cb);
        break;
    case MkGbRequestBye:
        ErrorCode = OnGbByeRequest(dynamic_cast<const CMkGbByeReqeust*>(pGbReq), Cb);
        break;
    case MkGbRequestInviteInfo:
        ErrorCode = OnGbPlayControlRequest(dynamic_cast<const CMkGbInviteInfoRequest*>(pGbReq), Cb);
        break;
    case MkGbReqeustInfo:
        //ErrorCode = OnGbInfoRequest(dynamic_cast<const Cmk)
        break;
    default:
        break;
    }
    return ErrorCode;
}


Uint32 CMkGb28181Test::OnGbDeviceAuthor(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    const CMkGbDeviceAuthorRequest *pAuthorReq = dynamic_cast<const CMkGbDeviceAuthorRequest*>(pGbReq);
    if (!pAuthorReq) {
        return InvalidParams;
    }
    CMkGbDeviceAuthorResponse Res;
    Res.m_bRedirect = FALSE;
    Cb(NoneError, &Res);
    return NoneError;
}

Uint32 CMkGb28181Test::OnGbMessageRequest(const CMkGbMessageRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    CMkGbMessageResponse Res;
    CMkGbMessageResponse* pRes = nullptr;
    Uint32 ErrorCode = NoneError;
    if ("Notify" == pGbReq->m_MessageType) {
        if ("Keepalive" != pGbReq->m_CmdType) {
            Res.m_Message.MainParam["Result"] = "OK";
            pRes = &Res;
        }
    } else if ("Query" == pGbReq->m_MessageType)  //up server query
    {
        if ("Catalog" == pGbReq->m_CmdType) {
            Res.m_SumNum = 3;
            Res.m_Message.ChildKey = "DeviceList";
            Res.m_Message.ItemName = "Item";
            MkGbMessage GbChild;
            GbChild.MainParam["Address"] = m_ChannelItem.Address;
            GbChild.MainParam["CivilCode"] = m_ChannelItem.CivilCode;
            GbChild.MainParam["DeviceID"] = m_ChannelItem.DeviceID;
            GbChild.MainParam["Manufacturer"] = m_ChannelItem.Manufacturer;
            GbChild.MainParam["Model"] = m_ChannelItem.Model;
            GbChild.MainParam["Name"] = m_ChannelItem.Name;
            GbChild.MainParam["Owner"] = m_ChannelItem.Owner;
            GbChild.MainParam["ParentID"] = m_ChannelItem.ParentID;
            GbChild.MainParam["Parental"] = m_ChannelItem.Parental;
            GbChild.MainParam["RegisterWay"] = m_ChannelItem.RegisterWay;
            GbChild.MainParam["SafetyWay"] = m_ChannelItem.SafetyWay;
            GbChild.MainParam["Secrecy"] = m_ChannelItem.Secrecy;
            GbChild.MainParam["Status"] = m_ChannelItem.Status;
            Res.m_Message.VecChildren.emplace_back(GbChild);
            GbChild.MainParam.clear();

            GbChild.MainParam["Address"] = m_AlarmItem.Address;
            GbChild.MainParam["CivilCode"] = m_AlarmItem.CivilCode;
            GbChild.MainParam["DeviceID"] = m_AlarmItem.DeviceID;
            GbChild.MainParam["Manufacturer"] = m_AlarmItem.Manufacturer;
            GbChild.MainParam["Model"] = m_AlarmItem.Model;
            GbChild.MainParam["Name"] = m_AlarmItem.Name;
            GbChild.MainParam["Owner"] = m_AlarmItem.Owner;
            GbChild.MainParam["ParentID"] = m_AlarmItem.ParentID;
            GbChild.MainParam["Parental"] = m_AlarmItem.Parental;
            GbChild.MainParam["RegisterWay"] = m_AlarmItem.RegisterWay;
            GbChild.MainParam["SafetyWay"] = m_AlarmItem.SafetyWay;
            GbChild.MainParam["Secrecy"] = m_AlarmItem.Secrecy;
            GbChild.MainParam["Status"] = m_AlarmItem.Status;
            Res.m_Message.VecChildren.emplace_back(GbChild);
            GbChild.MainParam.clear();

            GbChild.MainParam["Address"] = m_AudioOutItem.Address;
            GbChild.MainParam["CivilCode"] = m_AudioOutItem.CivilCode;
            GbChild.MainParam["DeviceID"] = m_AudioOutItem.DeviceID;
            GbChild.MainParam["Manufacturer"] = m_AudioOutItem.Manufacturer;
            GbChild.MainParam["Model"] = m_AudioOutItem.Model;
            GbChild.MainParam["Name"] = m_AudioOutItem.Name;
            GbChild.MainParam["Owner"] = m_AudioOutItem.Owner;
            GbChild.MainParam["ParentID"] = m_AudioOutItem.ParentID;
            GbChild.MainParam["Parental"] = m_AudioOutItem.Parental;
            GbChild.MainParam["RegisterWay"] = m_AudioOutItem.RegisterWay;
            GbChild.MainParam["SafetyWay"] = m_AudioOutItem.SafetyWay;
            GbChild.MainParam["Secrecy"] = m_AudioOutItem.Secrecy;
            GbChild.MainParam["Status"] = m_AudioOutItem.Status;
            Res.m_Message.VecChildren.emplace_back(GbChild);
            pRes = &Res;
        }
    } else if ("Control" == pGbReq->m_MessageType) {
        if ("DeviceControl" == pGbReq->m_CmdType) {
            MkMapString::const_iterator it = pGbReq->m_Message.MainParam.find("PTZCmd");
            if (it != pGbReq->m_Message.MainParam.end()) {
                CGbPtzCommand* pCmd = CGbPtzCommand::FromString(it->second);
                MkDebugLog("recv ptz cmd:%d param1:%d, param2:%d, param3:%d\n", pCmd->GetCmdType(), pCmd->GetParam1(), pCmd->GetParam2(), pCmd->GetParam3());
                MkDelete(pCmd);
            }
        }
    }
    Cb(NoneError, pRes);
    return ErrorCode;
}

Uint32 CMkGb28181Test::OnGbNotifyReqeust(const CMkGbNotifyRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    CMkGbNotifyResponse Res;
    Res.m_Message.MainParam["Result"] = "OK";
    Cb(NoneError, &Res);
    return NoneError;
}

Uint32 CMkGb28181Test::OnGbSubscribeRequest(const CMkGbSubscribeRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    CMkGbResponse Res;
    Res.m_Message.MainParam["Result"] = "OK";
    Cb(NoneError, &Res);
    MkString SubscribeId = pGbReq->m_SubscribeId;
    Uint32 Expires = pGbReq->m_Expires;
    MkString Event = pGbReq->m_Event;
    GetEventPool()->GetFreeEvent()->AddPipTask([this, SubscribeId, Expires, Event]() {
        CMkGbNotifyRequest Req;
        Req.m_SubscribeId = SubscribeId;
        Req.m_MessageType = "Notify";
        Req.m_CmdType = "Catalog";
        Req.m_DstId = "34000000002000000001";
        Req.m_DeviceId = GetSipId();
        Req.m_Expires = Expires;
        Req.m_State = "active";
        Req.m_Event = Event;
        Req.m_Message.MainParam["Status"] = "OK";
        Req.m_Message.MainParam["SumNum"] = "3";
        Req.m_Message.ChildKey = "DeviceList";
        Req.m_Message.ItemName = "Item";
        MkGbMessage ChildMsg;
        ChildMsg.MainParam["DeviceID"] = m_ChannelItem.DeviceID;
        ChildMsg.MainParam["Event"] = "ON";
        Req.m_Message.VecChildren.emplace_back(ChildMsg);
        ChildMsg.MainParam["DeviceID"] = m_AlarmItem.DeviceID;
        ChildMsg.MainParam["Event"] = "ON";
        Req.m_Message.VecChildren.emplace_back(ChildMsg);
        ChildMsg.MainParam["DeviceID"] = m_AudioOutItem.DeviceID;
        ChildMsg.MainParam["Event"] = "ON";
        Req.m_Message.VecChildren.emplace_back(ChildMsg);
        NotifyRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    });
    return NoneError;
}

Uint32 CMkGb28181Test::OnGbInviteRequest(const CMkGbInviteReqeust* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    CMkSdp OfferSdp;
    CMkSdp AnwerSdp;
    CMkSdpMedia AnwerSdpMedia;
    if (pGbReq->m_OfferSdp.empty()) {
        AnwerSdp.SetOrigin(CMkOrigin(GetSipId(), "0", "0", "IN", "IP4", GetTcpPublicHost()));
        AnwerSdp.SetConnection(CMkSdpConnection("IN", "IP4", GetTcpPublicHost()));
        AnwerSdpMedia.SetPort(111);
        AnwerSdpMedia.SetProtocol("TCP/RTP/AVP");

        AnwerSdp.SetVersion("0");
        MkString Session;
        CMkUtil::CreateRandomString(Len16, Session);
        AnwerSdp.SetSessionName(Session);
        AnwerSdp.SetTime(CMkSdpTime(0, 0, MkVectorString()));
        AnwerSdpMedia.SetMediaType("video");
        CMkSdpFmt SdpFmt;
        SdpFmt.SetPayload(96);
        SdpFmt.SetEncodingName("PS");
        SdpFmt.SetClockRate(MkDefaultClockRate);
        AnwerSdpMedia.AddFmt(SdpFmt);
        AnwerSdpMedia.AddAttr(CMkSdpAttribute("recvonly"));
        AnwerSdpMedia.AddAttr(CMkSdpAttribute("setup", "passive"));
        AnwerSdpMedia.AddAttr(CMkSdpAttribute("connection", "new"));
        AnwerSdpMedia.AddExtend("y", "111");
    } else {
        Uint32 ErrorCode = OfferSdp.ParseContent(pGbReq->m_OfferSdp);
        if (NoneError != ErrorCode || OfferSdp.GetMedia().empty()) {
            return InvalidParams;
        }
        CMkSdpMedia OffserSdpMedia = *OfferSdp.GetMedia().begin();
        CMkSdpFmt UseFmt;
        MkMap<Uint32, CMkSdpFmt>::const_iterator itFmt = OffserSdpMedia.GetFmts().begin();
        for (; itFmt != OffserSdpMedia.GetFmts().end(); itFmt++) {
            //only support ps stream
            if ("PS" == itFmt->second.GetEncodingName()) {
                UseFmt = itFmt->second;
                break;
            }
        }
        if (itFmt == OffserSdpMedia.GetFmts().end()) {
            Cb(MkSipStatusUnsupportedCodec, nullptr);
            return NoneError;
        }
        MkString SetUpValue;
        MkVector<CMkSdpAttribute>::const_iterator it = OffserSdpMedia.GetAttributes().begin();
        for (; it != OffserSdpMedia.GetAttributes().end(); it++) {
            if ("recvonly" == it->GetField()) {
                AnwerSdpMedia.AddAttr(CMkSdpAttribute("sendonly"));
            }
            if ("sendonly" == it->GetField()) {
                AnwerSdpMedia.AddAttr(CMkSdpAttribute("recvonly"));
            }
            if ("setup" == it->GetField()) {
                SetUpValue = it->GetValue();
            }
        }

        if ("TCP/RTP/AVP" == OffserSdpMedia.GetProtocol()) {
            if ("active" == SetUpValue) {
                AnwerSdpMedia.AddAttr(CMkSdpAttribute("setup", "passive"));
            } else {
                AnwerSdpMedia.AddAttr(CMkSdpAttribute("setup", "active"));
            }
            AnwerSdpMedia.AddAttr(CMkSdpAttribute("connection", "new"));
            AnwerSdpMedia.SetProtocol("TCP/RTP/AVP");
            AnwerSdpMedia.SetPort(123);
        } else {  //udp
            AnwerSdpMedia.SetPort(123);
            AnwerSdpMedia.SetProtocol("RTP/AVP");
        }


        AnwerSdp.SetOrigin(CMkOrigin(GetSipId(), "0", "0", "IN", "IP4", "127.0.0.1"));
        AnwerSdp.SetConnection(CMkSdpConnection("IN", "IP4", "127.0.0.1"));


        AnwerSdp.SetVersion("0");
        AnwerSdp.SetSessionName("Play");
        AnwerSdp.SetTime(CMkSdpTime(0, 0));;
        AnwerSdpMedia.SetMediaType("video");
        CMkSdpFmt SdpFmt;
        SdpFmt.SetPayload(96);
        SdpFmt.SetEncodingName("PS");
        SdpFmt.SetClockRate(MkDefaultClockRate);
        AnwerSdpMedia.AddFmt(SdpFmt);

        AnwerSdpMedia.AddExtend("y", "1213");
    }

    AnwerSdp.AddMedia(AnwerSdpMedia);
    CMkGbInviteResponse Res;
    AnwerSdp.ToString(Res.m_AnwserSdp);
    Cb(NoneError, &Res);
    return NoneError;
}

Uint32 CMkGb28181Test::OnGbByeRequest(const CMkGbByeReqeust* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    Cb(NoneError, nullptr);
    return NoneError;
}

Uint32 CMkGb28181Test::OnGbPlayControlRequest(const CMkGbInviteInfoRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    CMkGbInviteInfoResponse Res;
    Res.m_ControlType = pGbReq->m_ControlType;
    Res.m_DragSecond = pGbReq->m_DragSecond;
    Res.m_fSleep = pGbReq->m_fSleep;
    Res.m_SessionId = pGbReq->m_SessionId;
    Cb(NoneError, &Res);
    return NoneError;
}

Uint32 CMkGb28181Test::RegisterServer(const CMkGbDeviceAuthorRequest& Req, const MkRegCallback& Cb)
{
    return RegisterRequest(Req, [this, Req, Cb](Uint32 ErrorCode, const CMkGbResponse* pResponse) {
        const CMkGbDeviceAuthorResponse *pRes = dynamic_cast<const CMkGbDeviceAuthorResponse*>(pResponse);
        if (MkSipStatusRequestTimeout + SipResponseErrorBegin == ErrorCode && 0 == Req.m_Expires) {
            DeleteRouter(Req.m_RouterId);
        }
        if (MkSipStatusUnauthorized + SipResponseErrorBegin == ErrorCode && pRes) {
            MkString Realm = pRes->m_Realm.substr(1, pRes->m_Realm.size() - 2);
            MkString Nonce = pRes->m_Nonce.substr(1, pRes->m_Nonce.size() - 2);

            if ("MD5" == pRes->m_Algorithm) {
                MkString Ha1 = CMkMd5Encode::Encode("admin:" + Realm + ":admin");
                MkString Ha2 = CMkMd5Encode::Encode("REGISTER:" + pRes->m_Uri);
                MkString Ha3 = CMkMd5Encode::Encode(Ha1 + ":" + Nonce + ":" + Ha2);
                CMkGbDeviceAuthorRequest ReReq;
                ReReq.m_AuthorType = pRes->m_AuthType;
                ReReq.m_UserName = "admin";
                ReReq.m_Algorithm = pRes->m_Algorithm;
                ReReq.m_Expires = Req.m_Expires;
                ReReq.m_Realm = Realm;
                ReReq.m_Nonce = Nonce;
                ReReq.m_RouterId = Req.m_RouterId;
                ReReq.m_Response = Ha3;
                ReReq.m_Uri = pRes->m_Uri;
                ReReq.m_DstId = Req.m_DstId;
                ReReq.m_RegisterId = pRes->m_RegisterId;
                RegisterServer(ReReq, Cb);
            } else {
                ErrorCode = InvalidParams;
            }
        } else if (NoneError == ErrorCode) {
            if (0 == Req.m_Expires) {
                DeleteRouter(Req.m_RouterId);
            } else {
                m_RegServerId = Req.m_RouterId;
                KeepAliveServer();
                GetTimer()->AddTimer([this]() {
                    KeepAliveServer();
                }, 2000, m_KeepAliveTimer);
                Cb();
            }
        }
    });
}

Uint32 CMkGb28181Test::KeepAliveServer()
{
    CMkGbMessageRequest Req;
    Req.m_RouterId = m_RegServerId;
    Req.m_DstId = m_RegServerId;
    Req.m_DeviceId = GetSipId();
    Req.m_CmdType = "Keepalive";
    Req.m_MessageType = "Notify";
    return MessageRequest(Req, nullptr);
}


CMkGb28181Ut::CMkGb28181Ut()
{

}

CMkGb28181Ut::~CMkGb28181Ut()
{

}

void CMkGb28181Ut::SetUp()
{
    static int nIndex = 0;
    nIndex++;
    m_UpServerId = "340000000020000001";
    m_ServerId = "340200000020000001";
    m_EndUserId = "340200000040000001";
    m_GbRealm = "3402000000";
    m_UpServerRealm = "3400000000";
    m_pEventPool = nullptr;
    m_pTimer = nullptr;
    m_pGbEndUser = nullptr;
    m_pGbUpServer = nullptr;
    m_pGbCurServer = nullptr;
    m_pGbDevice = nullptr;
    m_WaitHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);

    m_pEventPool = new CMkEventPool;
    m_pEventPool->Start(1);
    m_pTimer = new CMkTimer;
    m_pTimer->StartTimerThread();

    m_pGbUpServer = new CMkGb28181Test(m_pEventPool, m_pTimer);
    while (1) {
        m_UpServerPort = CMkUtil::GetRandomNumber() % 0xFFFF;
        MkGbStartParam Param;
        Param.SipId = m_UpServerId;
        Param.SipRealm = m_UpServerRealm;
        Param.LocalHost = "127.0.0.1";
        Param.LocalPort = m_UpServerPort;
        Param.MappingHost = "";
        Param.MappingPort = 0;
        Param.RegisterExpires = 1;
        Param.SubscribeExpires = 1;
        Param.bCheckDstId = TRUE;
        if (NoneError == m_pGbUpServer->Start(Param)) {
            break;
        }
    }

    m_pGbCurServer = new CMkGb28181Test(m_pEventPool, m_pTimer);
    m_pGbCurServer->AddRouter(m_UpServerId, m_UpServerRealm, "127.0.0.1", m_UpServerPort, nIndex % 2);
    while (1) {
        m_ServerPort = CMkUtil::GetRandomNumber() % 0xFFFF;
        MkGbStartParam Param;
        Param.SipId = m_ServerId;
        Param.SipRealm = m_GbRealm;
        Param.LocalHost = "127.0.0.1";
        Param.LocalPort = m_ServerPort;
        Param.MappingHost = "";
        Param.MappingPort = 0;
        Param.RegisterExpires = 1;
        Param.SubscribeExpires = 1;
        Param.bCheckDstId = FALSE;
        if (NoneError == m_pGbCurServer->Start(Param)) {
            break;
        }
    }

    m_pGbEndUser = new CMkGbEndUser(m_pEventPool, m_pTimer);
    while (1) {
        m_EndUserPort = CMkUtil::GetRandomNumber() % 0xFFFF;
        MkGbStartParam Param;
        Param.SipId = m_EndUserId;
        Param.SipRealm = m_GbRealm;
        Param.LocalHost = "127.0.0.1";
        Param.LocalPort = m_EndUserPort;
        Param.MappingHost = "";
        Param.MappingPort = 0;
        Param.RegisterExpires = 1;
        Param.SubscribeExpires = 1;
        Param.bCheckDstId = TRUE;
        if (NoneError == m_pGbEndUser->Start(Param)) {
            break;
        }
    }

    CMkGbDeviceAuthorRequest Req;
    Req.m_RouterId = m_UpServerId;
    Req.m_DstId = m_UpServerId;
    Req.m_Realm = m_UpServerRealm;
    Req.m_Expires = 1;
    m_pGbCurServer->RegisterServer(Req, [this]() {
        SetEvent(m_WaitHandle);
    });
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    m_pGbEndUser->SetRegisterServer(m_ServerId, m_GbRealm, "127.0.0.1", m_ServerPort, (nIndex + 1) % 2, "admin", "admin", 1, 10, 2, [this](BOOL bOnline) {
        SetEvent(m_WaitHandle);
    });
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
}

void CMkGb28181Ut::TearDown()
{
    m_pGbCurServer->DeleteRouter(m_UpServerId);
    CMkThread::ThreadSleep(100);
    m_pTimer->StopTimerThread();
    m_pEventPool->Stop();
    MkDelete(m_pGbEndUser);
    MkDelete(m_pGbUpServer);
    MkDelete(m_pGbCurServer);
    MkDelete(m_pGbDevice);
    CloseHandle(m_WaitHandle);
    MkDelete(m_pTimer);
    MkDelete(m_pEventPool);
}


TEST_F(CMkGb28181Ut, InviteTest)
{
    CMkSdp Sdp;
    CMkSdpMedia SdpMedia;
    Sdp.SetOrigin(CMkOrigin(m_ServerId, "0", "0", "IN", "IP4", "127.0.0.1"));
    Sdp.SetConnection(CMkSdpConnection("IN", "IP4", "127.0.0.1"));
    SdpMedia.SetPort(1233);
    SdpMedia.SetProtocol("TCP/RTP/AVP");

    Sdp.SetVersion("0");
    Sdp.SetSessionName("Play");
    Sdp.SetTime(CMkSdpTime(0, 0));;
    SdpMedia.SetMediaType("video");
    CMkSdpFmt SdpFmt;
    SdpFmt.SetPayload(96);
    SdpFmt.SetEncodingName("PS");
    SdpFmt.SetClockRate(MkDefaultClockRate);
    SdpMedia.AddFmt(SdpFmt);
    SdpMedia.AddAttr(CMkSdpAttribute("recvonly"));
    SdpMedia.AddAttr(CMkSdpAttribute("setup", "active"));   //mast active
    SdpMedia.AddAttr(CMkSdpAttribute("connection", "new"));

    SdpMedia.AddExtend("y", "1213");
    Sdp.AddMedia(SdpMedia);
    MkString OfferSdp;
    Sdp.ToString(OfferSdp);
    Uint32 ErrorCode = m_pGbUpServer->InviteRequest(m_ServerId, "340200000013200001", "340200000013200001:0," + m_ServerId + ":1", OfferSdp, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        const CMkGbInviteResponse* pInviteRes = dynamic_cast<const CMkGbInviteResponse*>(pGbRes);
        EXPECT_NE(nullptr, pInviteRes);
        if (pInviteRes) {
            pInviteRes->m_EventResCb(MkMapString(), "");
            m_InviteSession = pInviteRes->m_SessionId;
        }
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    CMkGbMessageRequest Req;
    Req.m_CmdType = "MediaStatus";
    Req.m_DeviceId = "340200000013200001";
    Req.m_MessageType = "Notify";
    Req.m_Message.MainParam["NotifyType"] = "121";
    ErrorCode = m_pGbUpServer->InviteMessageRequest(Req, m_InviteSession, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    ErrorCode = m_pGbUpServer->InviteInfoRequest(m_InviteSession, MkGbPlayControlSeek, 1.0, 100, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    ErrorCode = m_pGbUpServer->InviteInfoRequest(m_InviteSession, MkGbPlayControlPause, 1.0, 0, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    ErrorCode = m_pGbUpServer->InviteInfoRequest(m_InviteSession, MkGbPlayControlReStore, 1.0, 0, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    ErrorCode = m_pGbUpServer->InviteInfoRequest(m_InviteSession, MkGbPlayControlSetSpeed, 2.0, 0, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    ErrorCode = m_pGbUpServer->ByeRequest(m_InviteSession, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
}

TEST_F(CMkGb28181Ut, SubscribeTest)
{
    CMkGbSubscribeRequest Req;
    Req.m_DstId = m_ServerId;
    Req.m_RouterId = m_ServerId;
    Req.m_DeviceId = m_ServerId;
    Req.m_CmdType = "Catalog";
    Req.m_MessageType = "Query";
    Req.m_Expires = 1;
    Req.m_Event = "presence";
    Uint32 ErrorCode = m_pGbUpServer->SubscribeRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        const CMkGbSubscribeResponse *pSubRes = dynamic_cast<const CMkGbSubscribeResponse*>(pGbRes);
        EXPECT_NE(nullptr, pSubRes);
        if (pSubRes) {
            m_SubscribeId = pSubRes->m_SubscribeId;
        }
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
    CMkThread::ThreadSleep(100);  //wait subscribe notify
    Req.m_Expires = 0;
    ErrorCode = m_pGbUpServer->SubscribeRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        const CMkGbSubscribeResponse *pSubRes = dynamic_cast<const CMkGbSubscribeResponse*>(pGbRes);
        EXPECT_NE(nullptr, pSubRes);
        if (pSubRes) {
            m_SubscribeId = pSubRes->m_SubscribeId;
        }
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    Req.m_CmdType = "bbb";
    ErrorCode = m_pGbUpServer->SubscribeRequest(Req, nullptr);
    EXPECT_NE(ErrorCode, NoneError);
}

TEST_F(CMkGb28181Ut, MessageTest)
{
    CMkGbMessageRequest Req;
    Req.m_DstId = m_ServerId;
    Req.m_RouterId = m_ServerId;
    Req.m_DeviceId = m_ServerId;
    Req.m_CmdType = "Catalog";
    Req.m_MessageType = "Query";
    Uint32 ErrorCode = m_pGbUpServer->MessageRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        const CMkGbMessageResponse *pMsgRes = dynamic_cast<const CMkGbMessageResponse*>(pGbRes);
        EXPECT_NE(nullptr, pMsgRes);
        if (pMsgRes) {
            EXPECT_EQ(3, pMsgRes->m_SumNum);
        }
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    Req.m_CmdType = "aaa";
    ErrorCode = m_pGbUpServer->MessageRequest(Req, nullptr);
    EXPECT_NE(NoneError, ErrorCode);
}

TEST_F(CMkGb28181Ut, DeviceControlTest)
{
    CMkGbMessageRequest Req;
    Req.m_DstId = "34020000001310000001";
    Req.m_RouterId = m_ServerId;
    Req.m_DeviceId = m_ServerId;
    Req.m_CmdType = "DeviceControl";
    Req.m_MessageType = "Control";
    CGbPtzCommand *pPtzCmd = CGbPtzCommand::CreateNew(MkGbPtzUp, 1, 1, 1);
    MkString StringPtz;
    pPtzCmd->ToGbString(StringPtz);
    MkDelete(pPtzCmd);
    Req.m_Message.MainParam["PTZCmd"] = StringPtz;
    Uint32 ErrorCode = m_pGbUpServer->MessageRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        EXPECT_EQ(NoneError, ErrorCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
}

TEST_F(CMkGb28181Ut, EndUserPlayTest)
{
    MkRtpParam Param;
    Param.bTcp = FALSE;
    Param.Host = "127.0.0.1";
    Param.Payload = 100;
    Param.Port = 12;
    Param.Ssrc = 0x111;
    Uint32 ErrorCode = m_pGbEndUser->StartPlay("sip:34020000001410000001@127.0.0.1:" + std::to_string(m_ServerPort), FALSE, 1, Param, [this](Uint32 ErrorCode, const MkString& SessionId, const MkRtpParam& AnswerRtpParam,const EventResponseCallback& EventCb) {
        EXPECT_EQ(NoneError, ErrorCode);
        m_InviteSession = SessionId;
        if (EventCb) {
            EventCb(MkMapString(), "");
        }
        SetEvent(m_WaitHandle);
    }, [this](const MkString& SessionId) {

    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
    m_pGbEndUser->StopPlay(m_InviteSession);

    ErrorCode = m_pGbEndUser->StartPlay("34020000001410000001", "Play", NowMkTime, NowMkTime, 1, Param, [this](Uint32 ErrorCode, const MkString& SessionId, const MkRtpParam& AnswerRtpParam,const EventResponseCallback& EventCb) {
        EXPECT_EQ(NoneError, ErrorCode);
        m_InviteSession = SessionId;
        if (EventCb) {
            EventCb(MkMapString(), "");
        }
        SetEvent(m_WaitHandle);
    }, [this](const MkString& SessionId) {

    });
    EXPECT_EQ(NoneError, ErrorCode);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
    m_pGbEndUser->StopPlay(m_InviteSession);
}

TEST_F(CMkGb28181Ut, EndUserPublishTest)
{
    MkRtpParam Param;
    Param.bTcp = FALSE;
    Param.Host = "127.0.0.1";
    Param.Payload = 100;
    Param.Port = 12;
    Param.Ssrc = 0x111;
    Uint32 ErrorCode = NoneError;
    //ErrorCode = m_pGbEndUser->StartPublish("34020000001410000001", Param, [this](Uint32 ErrorCode, const MkString& SessionId, const MkRtpParam& AnswerRtpParam) {
    //    EXPECT_EQ(NoneError, ErrorCode);
    //    m_InviteSession = SessionId;
    //    SetEvent(m_WaitHandle);
    //}, [this](const MkString& SessionId) {

    //});
    //WaitForSingleObject(m_WaitHandle, 0xFFFF);
    //m_pGbEndUser->StopPublish(m_InviteSession);

    ErrorCode = m_pGbEndUser->StartPublish("sip:34020000001410000001@127.0.0.1:" + std::to_string(m_ServerPort), FALSE, Param, [this](Uint32 ErrorCode, const MkString& SessionId, const MkRtpParam& AnswerRtpParam,const EventResponseCallback& EventCb) {
        EXPECT_EQ(NoneError, ErrorCode);
        m_InviteSession = SessionId;
        if (EventCb) {
            EventCb(MkMapString(), "");
        }
        SetEvent(m_WaitHandle);
    }, [this](const MkString& SessionId) {

    });
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
    m_pGbEndUser->StopPublish(m_InviteSession);

    ErrorCode = m_pGbEndUser->StartPublish2("sip:34020000001410000001@127.0.0.1:" + std::to_string(m_ServerPort), FALSE, Param, [this](Uint32 ErrorCode, const MkString& SessionId, const MkRtpParam& AnswerRtpParam,const EventResponseCallback& EventCb) {
        EXPECT_EQ(NoneError, ErrorCode);
        m_InviteSession = SessionId;
        if (EventCb) {
            EventCb(MkMapString(), "");
        }
        SetEvent(m_WaitHandle);
    }, [this](const MkString& SessionId) {

    });
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
    m_pGbEndUser->StopPublish(m_InviteSession);
}